/*
 * Copyright 2009 Gal Dolber
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.user.dragdrop.client;

import java.util.HashMap;

import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.DOM;

/**
 * Drop controller
 */
public class DropController {

	/**
	 * The tracking hash map
	 */
	private static HashMap<Element, DropController> dropMap = new HashMap<Element, DropController>();

	/**
	 * The last DropController assigned
	 */
	private static DropController lastDragIn = null;

	/**
	 * Adds to the element drop capabilities
	 * 
	 * @param element
	 * @param impl
	 * @return
	 */
	public static DropController make(Element element, HasDropHandlers impl) {
		return new DropController(element, impl);
	}

	/**
	 * Fires drag drop event for the current DropController
	 * 
	 * @param controller
	 */
	public static void onDragDrop(DragController controller) {
		Element e = DOM.eventGetCurrentEvent().getEventTarget().cast();
		DropController current = dropMap.get(e);

		// Clean lastDragIn
		if (lastDragIn != null) {
			lastDragIn.isDragIn = false;
			lastDragIn = null;
		}

		// Fire onDragDrop
		if (current != null) {
			current.impl.onDragDrop(controller);
		}
	}

	/**
	 * Fires drag in or out event for the current DropController
	 * 
	 * @param controller
	 */
	public static void onDragMove(DragController controller) {
		Element e = DOM.eventGetCurrentEvent().getEventTarget().cast();
		DropController current = dropMap.get(e);

		// Fires onDragOut
		if (lastDragIn != null) {
			if (!lastDragIn.equals(current)) {
				lastDragIn.isDragIn = false;
				lastDragIn.impl.onDragOut(controller);
				lastDragIn = null;
			}
		}

		// Fires onDragIn
		if (current != null) {
			if (!current.isDragIn) {
				lastDragIn = current;
				current.isDragIn = true;
				current.impl.onDragIn(controller);
			}
		}
	}

	/**
	 * Implementation
	 */
	HasDropHandlers impl;

	/**
	 * The drop target element
	 */
	Element target;

	/**
	 * If it has some drag
	 */
	private boolean isDragIn = false;

	DropController(Element element, HasDropHandlers handler) {
		target = element;
		impl = handler;

		dropMap.put(element, this);
	}
}
